home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 42 / Amiga Format AFCD42 (Issue 126, Aug 1999).iso / -serious- / comms / other / slrn / slrn_src / src / nntp.c < prev    next >
C/C++ Source or Header  |  1999-05-14  |  9KB  |  428 lines

  1. /* Copyright (c) 1998 John E. Davis (davis@space.mit.edu)
  2.  *
  3.  * This file is part of slrn.
  4.  *
  5.  * Slrn is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License as published by the
  7.  * Free Software Foundation; either version 2, or (at your option) any
  8.  * later version.
  9.  * 
  10.  * Slrn is distributed in the hope that it will be useful, but WITHOUT
  11.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  12.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  13.  * for more details.
  14.  * 
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with Slrn; see the file COPYING.  If not, write to the Free
  17.  * Software Foundation, 59 Temple Place - Suite 330, 
  18.  * Boston, MA  02111-1307, USA.
  19.  */
  20.  
  21. #include "config.h"
  22. #include "slrnfeat.h"
  23.  
  24. #include <stdio.h>
  25.  
  26. #ifdef HAVE_STDLIB_H
  27. # include <stdlib.h>
  28. #endif
  29.  
  30. #ifdef HAVE_UNISTD_H
  31. # include <unistd.h>
  32. #endif
  33.  
  34. #include <string.h>
  35. #include <errno.h>
  36. #include <slang.h>
  37.  
  38. #include "jdmacros.h"
  39. #include "server.h"
  40.  
  41. #ifdef VMS
  42. # include "vms.h"
  43. #endif
  44.  
  45. int Slrn_Query_Reconnect = 1;
  46.  
  47. static Slrn_Server_Obj_Type NNTP_Server_Obj;
  48. static Slrn_Post_Obj_Type NNTP_Post_Obj;
  49.  
  50. static NNTP_Type *NNTP_Server;
  51. static int NNTP_Port = -1;
  52. static char *NNTP_Server_Name;
  53.  
  54. /* If 1, abort.  If -1, abort unless keyboard quit. */
  55. static int _NNTP_Abort_On_Disconnection;
  56.  
  57. static void _nntp_connection_lost_hook (NNTP_Type *s)
  58. {
  59.    if (_NNTP_Abort_On_Disconnection)
  60.      {
  61.     if ((_NNTP_Abort_On_Disconnection == -1) && SLKeyBoard_Quit)
  62.       return;
  63.  
  64.     slrn_exit_error ("Server connection to %s lost.  Cannot recover.", 
  65.              s->host);
  66.      }
  67. }
  68.  
  69. static int _nntp_interrupt_handler (void)
  70. {
  71.    (void) slrn_handle_interrupts ();
  72.  
  73.    if ((SLang_Error == USER_BREAK) || SLKeyBoard_Quit)
  74.      return -1;
  75.  
  76.    return 0;
  77. }
  78.  
  79. static void _nntp_reset (void)
  80. {
  81.    NNTP_Type *s = NNTP_Server;
  82.    
  83.    nntp_disconnect_server (s);
  84.    /* The next NNTP command will actually perform the reset. */
  85. }
  86.  
  87.    
  88. static void _nntp_close_server (void)
  89. {
  90.    NNTP_Type *s = NNTP_Server;
  91.    
  92.    NNTP_Server = NULL;
  93.    
  94.    if (s != NULL) nntp_close_server (s);
  95. }
  96.  
  97. static int _nntp_initialize_server (void)
  98. {
  99.    NNTP_Authorization_Hook = slrn_get_authorization;
  100.    SLTCP_Interrupt_Hook = _nntp_interrupt_handler;
  101.    
  102.    if (NNTP_Server != NULL)
  103.      nntp_close_server (NNTP_Server);
  104.    
  105.    if (NULL == (NNTP_Server = nntp_open_server (NNTP_Server_Name, NNTP_Port)))
  106.      return -1;
  107.    
  108.    if (-1 == nntp_has_cmd (NNTP_Server, "XOVER"))
  109.      {
  110.     _nntp_close_server ();
  111.     return -1;
  112.      }
  113.    
  114.    if (NNTP_Server->can_xover == 0)
  115.      {
  116.     slrn_message_now ("Server %s does not implement the XOVER command.", 
  117.               NNTP_Server->host);
  118.     NNTP_Server_Obj.sv_has_xover = 0;
  119.      }
  120.    else NNTP_Server_Obj.sv_has_xover = 1;
  121.    
  122.    NNTP_Server->flags |= NNTP_RECONNECT_OK;
  123.  
  124.    NNTP_Connection_Lost_Hook = _nntp_connection_lost_hook;
  125.    return 0;
  126. }
  127.  
  128.  
  129. static char *_nntp_read_line (char *buf, unsigned int len)
  130. {
  131.    int status;
  132.    
  133.    status = nntp_read_line (NNTP_Server, buf, len);
  134.    
  135.    if (status == 1)
  136.      return buf;
  137.    
  138.    if (status == 0)
  139.      {
  140.     _NNTP_Abort_On_Disconnection = 0;
  141.     return NULL;
  142.      }
  143.  
  144.    /* Read fail or user break.  Either way, we have to shut it down. */
  145.    _nntp_connection_lost_hook (NNTP_Server);
  146.    return NULL;
  147. }
  148.  
  149. static int _nntp_head_cmd (int id, char *msgid, int *real_idp)
  150. {
  151.    return nntp_head_cmd (NNTP_Server, id, msgid, real_idp);
  152. }
  153.  
  154. static int _nntp_select_article (int n, char *msgid)
  155. {
  156.    return nntp_article_cmd (NNTP_Server, n, msgid);
  157. }
  158.  
  159. static int _nntp_select_group (char *grp, int *min, int *max)
  160. {
  161.    return nntp_select_group (NNTP_Server, grp, min, max);
  162. }
  163.  
  164. static int _nntp_put_server_cmd (char *cmd, char *buf, unsigned int len)
  165. {
  166.    int code;
  167.    
  168.    if (-1 != (code = nntp_server_cmd (NNTP_Server, cmd)))
  169.      {
  170.     strncpy (buf, NNTP_Server->rspbuf, len);
  171.     if (len) buf[len - 1] = 0;
  172.      }
  173.    return code;
  174. }
  175.  
  176. static int _nntp_xpat_cmd (char *hdr, int rmin, int rmax, char *pat)
  177. {
  178.    return nntp_xpat_cmd (NNTP_Server, hdr, rmin, rmax, pat);
  179. }
  180.  
  181. static int _nntp_xhdr_cmd (char *hdr, int num, 
  182.                char *buf, unsigned int buflen)
  183. {
  184.    return nntp_xhdr_cmd (NNTP_Server, hdr, num, buf, buflen);
  185. }
  186.  
  187. static int _nntp_xgtitle_cmd (char *pat)
  188. {
  189.    return nntp_xgtitle_cmd (NNTP_Server, pat);
  190. }
  191.  
  192. static int _nntp_has_cmd (char *cmd)
  193. {
  194.    return nntp_has_cmd (NNTP_Server, cmd);
  195. }
  196.  
  197. static int _nntp_list_newsgroups (void)
  198. {
  199.    return nntp_list_newsgroups (NNTP_Server);
  200. }
  201.  
  202. static int _nntp_list_active (void)
  203. {
  204.    int code;
  205.    
  206.    code = nntp_list_active_cmd (NNTP_Server);
  207.    
  208.    if (OK_GROUPS == code)
  209.      _NNTP_Abort_On_Disconnection = 1;
  210.  
  211.    return code;
  212. }
  213.  
  214. static int _nntp_start_post (void)
  215. {
  216.    /* Make sure we're connected to a server -- won't be the case the first
  217.     * time we post if we're reading news from a local spool.  In this case
  218.     * a late connect is better as we don't bother the server until we need
  219.     * to.
  220.     */
  221.    if (NNTP_Server == NULL)
  222.      {
  223.     if (-1 == _nntp_initialize_server ())
  224.       return -1;
  225.      }
  226.  
  227.    return nntp_post_cmd (NNTP_Server);
  228. }
  229.  
  230. static int _nntp_end_post (void)
  231. {
  232.    int status;
  233.    
  234.    status = nntp_end_post (NNTP_Server);
  235.    
  236.    if (status == -1)
  237.      {
  238.     slrn_error ("Error writing to server.");
  239.     return -1;
  240.      }
  241.    
  242.    if (NNTP_Server->code != OK_POSTED)
  243.      {
  244.     slrn_error ("Article rejected: %s", NNTP_Server->rspbuf);
  245.     return -1;
  246.      }
  247.  
  248.    return 0;
  249. }
  250.  
  251.  
  252. static int _nntp_po_puts (char *buf)
  253. {
  254.    char *b;
  255.    
  256.    /* make sure \n --> \r\n */
  257.    b = buf;
  258.    while (NULL != (b = slrn_strchr (buf, '\n')))
  259.      {
  260.     unsigned int len;
  261.     
  262.     len = (unsigned int) (b - buf);
  263.     if ((-1 == nntp_write_server (NNTP_Server, buf, len))
  264.         || (-1 == nntp_write_server (NNTP_Server, "\r\n", 2)))
  265.       return -1;
  266.     
  267.     buf = b + 1;
  268.      }
  269.    
  270.    return nntp_fputs_server (NNTP_Server, buf);
  271. }
  272.  
  273. static int _nntp_po_printf (char *fmt, ...)
  274. {
  275.    va_list ap;
  276.    char buf[NNTP_BUFFER_SIZE];
  277.    
  278.    va_start (ap, fmt);
  279.    vsprintf (buf, fmt, ap);
  280.    va_end (ap);
  281.    
  282.    return _nntp_po_puts (buf);
  283. }
  284.  
  285. static int _nntp_xover_cmd (int min, int max)
  286. {   
  287.    int status;
  288.    
  289.    if (OK_XOVER == (status = nntp_xover_cmd (NNTP_Server, min, max)))
  290.      {
  291.     _NNTP_Abort_On_Disconnection = -1;
  292.      }
  293.    
  294.    return status;
  295. }
  296.  
  297.  
  298. static int _nntp_next_cmd (int *id)
  299. {
  300.    return nntp_next_cmd (NNTP_Server, id);
  301. }
  302.  
  303. static int nntp_init_objects (void)
  304. {
  305.    NNTP_Post_Obj.po_start = _nntp_start_post;
  306.    NNTP_Post_Obj.po_end = _nntp_end_post;
  307.    NNTP_Post_Obj.po_printf = _nntp_po_printf;
  308.    NNTP_Post_Obj.po_puts = _nntp_po_puts;
  309.    NNTP_Post_Obj.po_can_post = 1;
  310.    
  311.    NNTP_Server_Obj.sv_select_group = _nntp_select_group;
  312.    NNTP_Server_Obj.sv_read_line = _nntp_read_line;
  313.    NNTP_Server_Obj.sv_close = _nntp_close_server;
  314.    NNTP_Server_Obj.sv_initialize = _nntp_initialize_server;
  315.    NNTP_Server_Obj.sv_select_article = _nntp_select_article;
  316.    NNTP_Server_Obj.sv_put_server_cmd = _nntp_put_server_cmd;
  317.    NNTP_Server_Obj.sv_xpat_cmd = _nntp_xpat_cmd;
  318.    NNTP_Server_Obj.sv_xhdr_command = _nntp_xhdr_cmd;
  319.    NNTP_Server_Obj.sv_xgtitle_cmd = _nntp_xgtitle_cmd;
  320.    NNTP_Server_Obj.sv_has_cmd = _nntp_has_cmd;
  321.    NNTP_Server_Obj.sv_list_newsgroups = _nntp_list_newsgroups;
  322.    NNTP_Server_Obj.sv_list_active = _nntp_list_active;
  323.    
  324.    NNTP_Server_Obj.sv_has_xover = 0;
  325.    NNTP_Server_Obj.sv_nntp_xover = _nntp_xover_cmd;
  326.    NNTP_Server_Obj.sv_nntp_head = _nntp_head_cmd;
  327.    NNTP_Server_Obj.sv_nntp_next = _nntp_next_cmd;
  328.    NNTP_Server_Obj.sv_reset = _nntp_reset;
  329.    return 0;
  330. }
  331.  
  332. static int _nntp_get_server_name (void)
  333. {
  334.    char *host;
  335.    
  336.    if (NULL == (host = NNTP_Server_Name))
  337.      {
  338.     host = nntp_get_server_name ();
  339.     if (host == NULL)
  340.       return -1;
  341.      }
  342.    
  343.    NNTP_Server_Name = NNTP_Server_Obj.sv_name = slrn_safe_strmalloc (host);
  344.    return 0;
  345. }
  346.  
  347.  
  348. static int nntp_select_server_object (void)
  349. {
  350.    if (NNTP_Server_Obj.sv_select_group == NULL)
  351.      nntp_init_objects ();
  352.    
  353.    Slrn_Server_Obj = &NNTP_Server_Obj;
  354.    
  355.    if (NNTP_Server_Obj.sv_name == NULL)
  356.      return _nntp_get_server_name ();
  357.  
  358.    return 0;
  359. }
  360.  
  361. static int nntp_select_post_object (void)
  362. {
  363.    if (NNTP_Post_Obj.po_start == NULL)
  364.      nntp_init_objects ();
  365.    
  366.    Slrn_Pos